#include "utilities.h"

void *terminalCommands(void *ptr)
{
	int ind;
	char tempStatusFile[512];
	map<int,writeListData>::iterator it;
	fd_set rfds;
    struct timeval tv, time1, starttime;
	gettimeofday(&starttime,NULL);
    int retval;
	FD_ZERO(&rfds);
    FD_SET(fileno(stdin), &rfds);
    tv.tv_sec = initMap["AutoShutdown"].asDouble;
    tv.tv_usec = 0;
	cout<<"servant:"<<port_recieve<<"> ";
    fflush(stdout);
	retval = select(1, &rfds, NULL, NULL, &tv);
	while(1) 
	{
		ind = 0;
		if(retval==0)
		{
			break;
		}
		if(signalIntFlag)
		{
			signalIntFlag = 0;
			gettimeofday(&time1,NULL);
			tv.tv_sec = initMap["AutoShutdown"].asDouble-(time1.tv_sec-starttime.tv_sec);
			tv.tv_usec = 0;
			retval = select(1, &rfds, NULL, NULL, &tv);
		}
		fflush(stdout);
		if (FD_ISSET(fileno(stdin), &rfds))
		{ 
			cin.getline(input_line, 512);
			if(strcmp(input_line, "") == 0)
			{
				cout<<"Bad Command"<<endl;
				fflush(stdin);
				cout<<"servant:"<<port_recieve<<"> ";
				fflush(stdout);
				continue;
			}
			char *str;
			if(printFlag==1)
			{
				cout<<" ----- "<<input_line<<endl;
			}
			str = strtok(input_line, " ");
			char command[20];
			char type[20];
			int ttl;
			char TypeOfSearch[128];
			char ValueOfSearch[128];
			strcpy(command, str);
			ind++;
			if(strcmp(command, "shutdown") == 0)
			{
				tv.tv_sec = 0;
				tv.tv_usec = 0;
				retval = select(1, &rfds, NULL, NULL, &tv);
				notifyFlag = true;
				if(printFlag==1)
				{
					cout<<"Shutdown has been initiated"<<endl;
				}
				uint8_t notifyType = 1;
				char obj[256];
				strcpy(obj, "NTFY");
				msg_header notify_req;
				createMsgHdrStr(&notify_req,0xF7,1,obj,node_instance_id,sizeof(uint8_t));
				
				listBuffStruct lbtemp;
				memset(lbtemp.listBuff, '\0', 27+sizeof(uint8_t));
				fillMsgHdrBuffer(notify_req, lbtemp.listBuff);
				memcpy(&(lbtemp.listBuff[27]), &notifyType, sizeof(uint8_t));
				lbtemp.datalength = 27 + sizeof(uint8_t);
				lbtemp.logtype = 1;
				//Put it on every write queue
				pthread_mutex_lock(&writeMapMutex);
				if(printFlag==1)
				{
					cout<<"Size - "<<writeMap.size()<<endl;
				}
				for(it=writeMap.begin(); it!=writeMap.end(); it++)
				{
					lbtemp.portNumber = (*it).first;
					writeListData listDataStr = writeMap[(*it).first];
					listDataStr.response.push_back(lbtemp);
					writeMap[(*it).first] = listDataStr;
					pthread_mutex_lock(&notifyLock);
					notifyCount++;
					if(printFlag==1)
					{
						cout<<"Notify Count set - "<<notifyCount<<endl;
					}
					pthread_mutex_unlock(&notifyLock);
				}
				pthread_mutex_unlock(&writeMapMutex);
				pthread_mutex_lock(&notifyLock);
				if((notifyCount == 0 || writeMap.size() == 0) && notifyFlag)
				{
					if(printFlag==1)
					{
						cout<<"Ending"<<endl;
					}
					pthread_mutex_unlock(&notifyLock);
					serverShutdown = true;
					dieChild = true;
					if(printFlag==1)
					{
						cout<<statusFile<<endl;
					}
					close(globalAcceptSock);
					pthread_exit(NULL);
				}
				else
				{
					pthread_mutex_unlock(&notifyLock);
				}
				fflush(stdout);
				tv.tv_sec = 0;
				tv.tv_usec = 0;	
				retval = select(1, &rfds, NULL, NULL, &tv);
			}
			else if(strcmp(command, "status") == 0)
			{
				memset(tempStatusFile, '\0', 512);
				memset(statusFile, '\0', 128);
				while(str != NULL)
				{
					str = strtok(NULL, " ");
					if(str != NULL)
					{
						if(ind == 1)
						{
							strcpy(type, str);
						}
						if(ind == 2)
						{
							ttl = atoi(str);
						}
						if(ind == 3)
						{
							memcpy(tempStatusFile, str, strlen(str));
							char path[256];
							memset(path, '\0', 256);
							strcpy(path, tempStatusFile);
							FILE* filePt;
							filePt = fopen(path, "w");
							fclose(filePt);
						}
						ind++;
					}
				}
				if(ind != 4)
				{
					cout<<"Number of arguments do not match in command Line"<<endl;
					cout<<"servant:"<<port_recieve<<"> ";
					fflush(stdout);
					gettimeofday(&time1,NULL);
					tv.tv_sec = initMap["AutoShutdown"].asDouble-(time1.tv_sec-starttime.tv_sec);
					tv.tv_usec = 0;
					retval = select(1, &rfds, NULL, NULL, &tv);
					continue;
				}
				
				if(ttl != 0)
				{
					//Get response from other neighbors
					status_msg statMsg;
					if(strcmp(type, "neighbors") == 0)
					{
						statMsg.statustype = 0x01;
					}
					else if(strcmp(type, "files") == 0)
					{
						statMsg.statustype = 0x02;
					}
					else
					{
						cout<<"BAD COMMAND"<<endl;
						cout<<"servant:"<<port_recieve<<"> ";
						fflush(stdout);
						gettimeofday(&time1,NULL);
						tv.tv_sec = initMap["AutoShutdown"].asDouble-(time1.tv_sec-starttime.tv_sec);
						tv.tv_usec = 0;
						retval = select(1, &rfds, NULL, NULL, &tv);
					}
					char obj[256];
					strcpy(obj, "STRQ");
					if(printFlag==1)
					{
						cout<<tempStatusFile<<endl;
					}
					struct timeval t1;
					gettimeofday(&t1,NULL);
					globalStatusTime = (double)(t1.tv_sec * (1e+3) + (double)t1.tv_usec/1000);
					memcpy(&statusFile, &tempStatusFile, strlen(tempStatusFile));
					msg_header statusReq;
					createMsgHdrStr(&statusReq,0xAC,ttl,obj,node_instance_id,sizeof(status_msg));
					statusSTR sent;
					memcpy(sent.uoid,statusReq.uoid,20);
					if(strcmp(type, "neighbors") == 0)
					{
						if(printFlag == 1)
						{
							cout<<"set neigh"<<endl;
						}
						sent.statusType = (uint8_t)0x01;
						uint8_t t = 0x01;
						memcpy(&statType, &t, sizeof(uint8_t));
					}
					else if(strcmp(type, "files") == 0)
					{
						if(printFlag == 1)
						{
							cout<<"set files"<<endl;
						}
						sent.statusType = (uint8_t)0x02;
						uint8_t t = 0x02;
						memcpy(&statType, &t, sizeof(uint8_t));
					}
					statusResponseList.push_back(sent);
					
					//clear the response collecting list
					pthread_mutex_lock(&storeFilesLock);
					statusFilesDataList.clear();
					pthread_mutex_unlock(&storeFilesLock);
							
					listBuffStruct lbtemp;
					lbtemp.logtype = 1;
					memset(lbtemp.listBuff, '\0', 27+sizeof(status_msg));
					fillMsgHdrBuffer(statusReq, lbtemp.listBuff);
					memcpy(&(lbtemp.listBuff[27]), &statMsg, sizeof(status_msg));
					lbtemp.datalength = 27 + sizeof(status_msg);
					pthread_mutex_lock(&writeMapMutex);
					for(it=writeMap.begin(); it!=writeMap.end(); it++)
					{
						lbtemp.portNumber = (*it).first;
						writeListData listDataStr = writeMap[(*it).first];
						listDataStr.response.push_back(lbtemp);
						writeMap[(*it).first] = listDataStr;
					}
					pthread_mutex_unlock(&writeMapMutex);
					
					cout<<"Processing ..."<<endl;
					while(!dieChild)
					{
						if(globalStatusTime == 0 || globalStatusTime == -1)
						{
							break;
						}
						usleep(10);
					}
					if(signalIntFlag!=1)
					{
						cout<<"servant:"<<port_recieve<<"> ";
						fflush(stdout);
						gettimeofday(&time1,NULL);
						tv.tv_sec = initMap["AutoShutdown"].asDouble-(time1.tv_sec-starttime.tv_sec);
						tv.tv_usec = 0;
						retval = select(1, &rfds, NULL, NULL, &tv);
					}
				}
				else
				{
					if(strcmp(type, "neighbors") == 0)
					{
						memcpy(&statusFile, &tempStatusFile, strlen(tempStatusFile));
						if(printFlag == 1)
						{
							cout<<"****neigh status"<<endl;
						}
						//Just note down the neighbors of the current node onto a file
						FILE *file;
						char path[256];
						memset(path, '\0', 256);
						strcpy(path, statusFile);
						file = fopen(path, "w");
						if(file == NULL)
						{
							if(printFlag==1)
							{
								cout<<"Problem in opening the file"<<endl;
							}
							exit(0);
						}
						char dataStatus[256];
						memset(dataStatus, '\0', 256);
						strcpy(dataStatus, "V -t * -v 1.0a5\n");
						fputs(dataStatus, file);
						memset(dataStatus, '\0', 256);
						sprintf(dataStatus, "n -t * -s %d -c red -i black\n", port_recieve);
						fputs(dataStatus, file);
						pthread_mutex_lock(&writeMapMutex);
						for(it=writeMap.begin(); it!=writeMap.end(); it++)
						{
							memset(dataStatus, '\0', 256);
							sprintf(dataStatus, "n -t * -s %d -c red -i black\n", (*it).first);
							fputs(dataStatus, file);
						}
						for(it=writeMap.begin(); it!=writeMap.end(); it++)
						{
							memset(dataStatus, '\0', 256);
							sprintf(dataStatus, "l -t * -s %d -d %d -c blue\n", port_recieve, (*it).first);
							fputs(dataStatus, file);
						}
						pthread_mutex_unlock(&writeMapMutex);
						memset(statusFile, '\0', 128);
						fclose(file);
						cout<<"servant:"<<port_recieve<<"> ";
						fflush(stdout);
						gettimeofday(&time1,NULL);
						tv.tv_sec = initMap["AutoShutdown"].asDouble-(time1.tv_sec-starttime.tv_sec);
						tv.tv_usec = 0;
						retval = select(1, &rfds, NULL, NULL, &tv);
					}
					else if(strcmp(type, "files") == 0)
					{
						memcpy(&statusFile, &tempStatusFile, strlen(tempStatusFile));
						//clear the response collecting list
						pthread_mutex_lock(&storeFilesLock);
						statusFilesDataList.clear();
						pthread_mutex_unlock(&storeFilesLock);
						if(printFlag == 1)
						{
							cout<<"****Files status"<<endl;
						}
						FILE *filePt;
						char path[256];
						memset(path, '\0', 256);
						strcpy(path, statusFile);
						filePt = fopen(path, "w");
						if(filePt == NULL)
						{
							if(printFlag==1)
							{
								cout<<"Problem in opening the file"<<endl;
							}
							exit(0);
						}
						char line1[256];
						memset(line1, '\0', 256);
						sprintf(line1, "%s%s%d%s", hostname, ":", port_recieve, " has the following files\n");
						fputs(line1, filePt);
						list<storeListStr>::iterator itMyStoreList;
						int ksz = 0;
						uint32_t fileLen = 0;
						pthread_mutex_lock(&storelock);
						for(itMyStoreList = myStoreList.begin(); itMyStoreList != myStoreList.end(); itMyStoreList++)
						{
							fileLen = 0;
							char filename[128];
							char fileData[512];
							memset(fileData, '\0', 512);
							memset(filename, '\0', 128);
							strcpy(filename,initMap["HomeDir"].asStr);
							strcat(filename,"/");
							strcat(filename,"files/");
							char ind[10];
							memset(ind, '\0', 10);
							sprintf(ind, "%d", itMyStoreList->fileIndex);
							strcat(filename, ind);
							strcat(filename, ".meta");
							struct stat st;
							ksz = stat(filename, &st);
							fileLen = (uint32_t)st.st_size;
							FILE *fileP;
							fileP = fopen(filename, "r");
							fread(fileData, 1, fileLen, fileP);
							fclose(fileP);
							fwrite(fileData, 1, strlen(fileData), filePt);
						}
						pthread_mutex_unlock(&storelock);
						fclose(filePt);
						memset(statusFile, '\0', 128);
						cout<<"servant:"<<port_recieve<<"> ";
						fflush(stdout);
						gettimeofday(&time1,NULL);
						tv.tv_sec = initMap["AutoShutdown"].asDouble-(time1.tv_sec-starttime.tv_sec);
						tv.tv_usec = 0;
						retval = select(1, &rfds, NULL, NULL, &tv);
					}
				}
			}
			else if(strcmp(command, "store") == 0)
			{
				if(printFlag == 1)
				{
					cout<<"Store Command Entered"<<endl;
				}
				char filename[200],Keywords[20][128];
				int keycount = 0;
				
				while(str != NULL)
				{
					if(ind == 1)
					{
						str = strtok(NULL, " ");
						if(str != NULL)
						{
						strcpy(filename, str);
						}
						ind++;
					}
					else if(ind == 2)
					{
						str = strtok(NULL, " ");
						if(str != NULL)
						{
						ttl = atoi(str);
						}
						ind++;
					}
					else if(ind == 3)
					{
						str = strtok(NULL, " =\"");
						if(str!=NULL)
						{
							str = toLowerCase(str);
							strcpy(Keywords[keycount++], str);
						}
					}
				}
				
				storeListStr storeData = storeFunctionality(Keywords,filename,keycount);
				char ch[8192];
				listBuffStruct lbtemp;
				lbtemp.logtype = 1;
				memset(lbtemp.listBuff, '\0', 8192);
				msg_header storeReq;
				char obj[256];
				strcpy(obj, "STOR");
				char fc[10];
				memset(fc,'\0',10);
				sprintf(fc,"%d",storeData.fileIndex);
				char storefilename[512];
				strcpy(storefilename,initMap["HomeDir"].asStr);
				strcat(storefilename,"/");
				strcat(storefilename,"files");
				strcat(storefilename,"/");
				strcat(storefilename,fc);
				strcat(storefilename,".meta");
				struct stat st;
				int k = 0;
				k = stat(storefilename, &st);
				uint32_t sz = st.st_size;
				createMsgHdrStr(&storeReq,0xCC,ttl,obj,node_instance_id,sz + sizeof(uint32_t) + storeData.fileSize);		
				pthread_mutex_lock(&writeMapMutex);
				int forCounter = (sz + sizeof(uint32_t) + storeData.fileSize)/(8192);
				int extraCounter = (sz + sizeof(uint32_t) + storeData.fileSize)%(8192);
				for(it=writeMap.begin(); it!=writeMap.end(); it++)
				{
					if(drand48() < initMap["NeighborStoreProb"].asDouble)
					{
						memset(lbtemp.listBuff, '\0', 8192);
						fillMsgHdrBuffer(storeReq,lbtemp.listBuff);
						lbtemp.datalength = 27;
						lbtemp.portNumber = (*it).first;
						writeListData listDataStr = writeMap[(*it).first];
						listDataStr.response.push_back(lbtemp);
						int f = 0;
						FILE *pFile1;
						pFile1 = fopen(storefilename,"r");
						fread(&ch,1,sz,pFile1);
						memset(lbtemp.listBuff, '\0', 8192);
						memcpy(&(lbtemp.listBuff[0]),&sz,sizeof(uint32_t));
						memcpy(&(lbtemp.listBuff[4]),&ch,sz);
						fclose(pFile1);
						pFile1 = fopen(filename,"r");
						if(forCounter==0)
						{
							fread (&ch,1,storeData.fileSize,pFile1);
							memcpy(&(lbtemp.listBuff[4+sz]),&ch,storeData.fileSize);
							lbtemp.datalength = storeData.fileSize+4+sz;
							listDataStr.response.push_back(lbtemp);
						}
						else
						{
							fread (&ch,1,8192-sz-sizeof(uint32_t),pFile1);
							memcpy(&(lbtemp.listBuff[4+sz]),&ch,8192-sz-sizeof(uint32_t));
							lbtemp.datalength = 8192;
							listDataStr.response.push_back(lbtemp);
							for(f=1;f<forCounter;f++)
							{
								fread (&ch,1,8192,pFile1);
								memset(lbtemp.listBuff,'\0',8192);
								lbtemp.datalength = 8192;
								memcpy(&(lbtemp.listBuff[0]),&ch,8192);
								listDataStr.response.push_back(lbtemp);
							}
							
							if(extraCounter!=0)
							{
								fread (&ch,1,extraCounter,pFile1);
								memset(lbtemp.listBuff,'\0',8192);
								lbtemp.datalength = extraCounter;
								memcpy(&(lbtemp.listBuff[0]),&ch,extraCounter);
								listDataStr.response.push_back(lbtemp);
							}
						}
						fclose(pFile1);
						writeMap[(*it).first] = listDataStr;
					}
				}
				pthread_mutex_unlock(&writeMapMutex);
				cout<<"servant:"<<port_recieve<<"> ";
				fflush(stdout);
				gettimeofday(&time1,NULL);
				tv.tv_sec = initMap["AutoShutdown"].asDouble-(time1.tv_sec-starttime.tv_sec);
				tv.tv_usec = 0;
				retval = select(1, &rfds, NULL, NULL, &tv);
			}
			else if(strcmp(command, "search") == 0)
			{
				int l = 0;
				bool badCmd = false;
				memset(TypeOfSearch, '\0', 128);
				memset(ValueOfSearch, '\0', 128);
				while(str != NULL)
				{
					str = strtok(NULL, " =\"");
					strncpy(TypeOfSearch, str, strlen(str));
					while(str != NULL)
					{
						str = strtok(NULL, " =\"");
						if(str != NULL)
						{
							if(l == 0)
							{
								str = toLowerCase(str);
								strncpy(ValueOfSearch, str, strlen(str));
								l = -1;
							}
							else
							{
								str = toLowerCase(str);
								strcat(ValueOfSearch, " ");
								strcat(ValueOfSearch, str);
							}
						}
					}
				}
				
				search_request searchReq;
				if(strcmp(TypeOfSearch, "keywords") == 0)
				{
					searchReq.searchType = 3;
				}
				else if(strcmp(TypeOfSearch, "sha1hash") == 0)
				{
					searchReq.searchType = 2;
				}
				else if(strcmp(TypeOfSearch, "filename") == 0)
				{
					searchReq.searchType = 1;
				}
				else
				{
					badCmd = true;
				}				
				
				if(!badCmd)
				{
					if(printFlag == 1)
					{
						cout<<"search"<<endl;
					}
					getIndex = 0;
					getIndex++;
					globalSearchTime = 0;
					memset(searchReq.searchQuery, '\0', 512);
					if(searchReq.searchType == 2)
					{
						char uoidTe[20];
						convert40Bto20B(uoidTe, ValueOfSearch);
						memcpy(&searchReq.searchQuery, &uoidTe, 20);
					}
					else
					{
						memcpy(&searchReq.searchQuery, &ValueOfSearch, strlen(ValueOfSearch));
					}
					pthread_mutex_lock(&searchResultLock);
					searchResultList.clear();
					pthread_mutex_unlock(&searchResultLock);
						
					int dataL = sizeof(uint8_t) + strlen(searchReq.searchQuery);
					char obj[256];
					strcpy(obj, "SHRQ");
					msg_header searchReqHdr;
					createMsgHdrStr(&searchReqHdr,0xEC,initMap["TTL"].asDouble,obj,node_instance_id, dataL);
					
					//Push the requested uoid for matching during response requests
					searchSTR sent;
					memcpy(sent.uoid,searchReqHdr.uoid,20);
					searchResponseList.push_back(sent);
					
					listBuffStruct lbtemp;
					lbtemp.logtype = 1;
					memset(lbtemp.listBuff, '\0', 8192);
					fillMsgHdrBuffer(searchReqHdr, lbtemp.listBuff);
					memcpy(&(lbtemp.listBuff[27]), &searchReq.searchType, sizeof(uint8_t));
					memcpy(&(lbtemp.listBuff[28]), &searchReq.searchQuery, dataL-sizeof(uint8_t));
					lbtemp.datalength = 27 + dataL;
					pthread_mutex_lock(&writeMapMutex);
					for(it=writeMap.begin(); it!=writeMap.end(); it++)
					{
						lbtemp.portNumber = (*it).first;
						writeListData listDataStr = writeMap[(*it).first];
						listDataStr.response.push_back(lbtemp);
						writeMap[(*it).first] = listDataStr;
					}
					pthread_mutex_unlock(&writeMapMutex);
					cout<<"Processing ..."<<endl;
					
					//Search for the files in the local system and update the searchFileIdsList
					//Clear the searched files list before the new search
					pthread_mutex_lock(&searchFileIdsLock);
					searchFileIdsList.clear();
					pthread_mutex_unlock(&searchFileIdsLock);
					//Search for the files in the index files and store those indexes in searchFileIdsList
					searchFiles(searchReq);
					
					list<search_fileId_results>::iterator itSearFidsList;
					int ksz = 0;
					uint32_t fileLen = 0;
					char filename[128];
					char fileData[512];
					char sha1[20];
					//Take each Index from searchFileIdsList and display it to the terminal
					pthread_mutex_lock(&searchFileIdsLock);
					for(itSearFidsList = searchFileIdsList.begin(); itSearFidsList != searchFileIdsList.end(); itSearFidsList++)
					{
						search_fileId_results temp = *itSearFidsList;
						memset(fileData, '\0', 512);
						memset(filename, '\0', 128);
						strcpy(filename,initMap["HomeDir"].asStr);
						strcat(filename,"/");
						strcat(filename,"files/");
						char ind[10];
						memset(ind, '\0', 10);
						sprintf(ind, "%d", temp.fileIndex);
						strcat(filename, ind);
						strcat(filename, ".meta");
						struct stat st;
						ksz = stat(filename, &st);
						fileLen = (uint32_t)st.st_size;
						FILE *fileP;
						fileP = fopen(filename, "r");
						fread(fileData, 1, fileLen, fileP);
						fclose(fileP);
						
						pthread_mutex_lock(&getIndexLock);
						cout<<"["<<getIndex<<"] ";
						cout<<"FileID = ";
						for(int m=0;m<20;m++)
						{
							printf("%02x", (uint8_t)temp.fileUOID[m]);
						}
						cout<<endl;
						//display the results on the terminal
						memset(sha1, '\0', 20);
						displaySearchResults(fileData, sha1);
						
						//Copy the result to a list of structures which is used while GET request
						getSearchResults gSearRes;
						gSearRes.getIndex = getIndex;
						memset(gSearRes.fileId, '\0', 20);
						memcpy(&gSearRes.fileId, &(temp.fileUOID[0]), 20);
						memcpy(&gSearRes.fileSha1, &(sha1[0]), 20);
						pthread_mutex_lock(&searchResultLock);
						searchResultList.push_back(gSearRes);
						pthread_mutex_unlock(&searchResultLock);
						//increment the index of searche results count
						getIndex++;
						pthread_mutex_unlock(&getIndexLock);
					}
					pthread_mutex_unlock(&searchFileIdsLock);
					
					//Wait till the user presses CTRL+C
					while(!dieChild)
					{
						if(globalSearchTime == -1)
						{
							break;
						}
						usleep(10);
					}
					
					if(signalIntFlag!=1)
					{
						cout<<"servant:"<<port_recieve<<"> ";
						fflush(stdout);
						gettimeofday(&time1,NULL);
						tv.tv_sec = initMap["AutoShutdown"].asDouble-(time1.tv_sec-starttime.tv_sec);
						tv.tv_usec = 0;
						retval = select(1, &rfds, NULL, NULL, &tv);
					}
				}
				else
				{
					cout<<"Bad Command"<<endl;
					cout<<"servant:"<<port_recieve<<"> ";
					fflush(stdout);
					gettimeofday(&time1,NULL);
					tv.tv_sec = initMap["AutoShutdown"].asDouble-(time1.tv_sec-starttime.tv_sec);
					tv.tv_usec = 0;
					retval = select(1, &rfds, NULL, NULL, &tv);
				}
			}
			else if(strcmp(command, "delete") == 0)
			{
				if(printFlag == 1)
				{
					cout<<"Delete Command Entered"<<endl;
				}
				char filename[200],filesha1[100],nonce[100];
				
				while(str != NULL)
				{
					str = strtok(NULL, "=");
					if(str != NULL)
					{
						if(strcmp(str,"FileName")==0)
						{
							str = strtok(NULL, " ");
							strcpy(filename,str);
						}
						else if(strcmp(str,"SHA1")==0)
						{
							str = strtok(NULL, " ");
							strcpy(filesha1,str);
						}
						else if(strcmp(str,"Nonce")==0)
						{
							str = strtok(NULL, " ");
							strcpy(nonce,str);
						}
					}
				}
				if(printFlag == 1)
				{
					cout<<filename<<endl;
					cout<<filesha1<<endl;
					cout<<nonce<<endl;
				}
				list<storeListStr>::iterator itF;
				char storefilename[512];
				FILE *pFile;
				pthread_mutex_lock(&storelock);
				for(itF=myStoreList.begin(); itF!=myStoreList.end(); itF++)
				{
					storeListStr storeTemp = *itF;
					if(strcmp(storeTemp.fileName,filename)==0)
					{
						char sha1[20];
						convert40Bto20B(sha1, filesha1);
						int m = memcmp(storeTemp.fileSha1, sha1, 20);
						if(m == 0)
						{
							int index = storeTemp.fileIndex;
							if(printFlag == 1)
							{
								cout<<"File Found"<<endl;
								cout<<index<<endl;
							}
							char deleteMessage[8192];
							char tempMessage[200];
							memset(deleteMessage,'\0',8192);
							strcpy(tempMessage,"FileName=");
							memcpy(&(deleteMessage[0]),tempMessage,9);
							memcpy(&(deleteMessage[9]),storeTemp.fileName,strlen(storeTemp.fileName));
							strcpy(tempMessage,"\r\n");
							memcpy(&(deleteMessage[9+strlen(storeTemp.fileName)]),tempMessage,2);
							strcpy(tempMessage,"SHA1=");
							memcpy(&(deleteMessage[11+strlen(storeTemp.fileName)]),tempMessage,5);
							memcpy(&(deleteMessage[16+strlen(storeTemp.fileName)]),storeTemp.fileSha1,20);
							strcpy(tempMessage,"\r\n");
							memcpy(&(deleteMessage[36+strlen(storeTemp.fileName)]),tempMessage,2);
							strcpy(tempMessage,"Nonce=");
							memcpy(&(deleteMessage[38+strlen(storeTemp.fileName)]),tempMessage,6);
							memcpy(&(deleteMessage[44+strlen(storeTemp.fileName)]),storeTemp.fileNonce,20);
							strcpy(tempMessage,"\r\n");
							memcpy(&(deleteMessage[64+strlen(storeTemp.fileName)]),tempMessage,2);
							strcpy(tempMessage,"Password=");
							memcpy(&(deleteMessage[66+strlen(storeTemp.fileName)]),tempMessage,9);
							char fc[10];
							memset(fc,'\0',10);
							sprintf(fc,"%d",index);
							strcpy(storefilename,initMap["HomeDir"].asStr);
							strcat(storefilename,"/");
							strcat(storefilename,"files");
							strcat(storefilename,"/");
							strcat(storefilename,fc);
							strcat(storefilename,".pass");
							pFile = fopen(storefilename,"r");
							char userInput[200];
							if(pFile==NULL)
							{
								if(printFlag == 1)
								{
									cout<<"No one-time password found."<<endl;
								}
								cout<<"Okay to use a random password [yes/no] - ";
								cin>>userInput;
								fflush(stdin);
								if(printFlag == 1)
								{
									cout<<userInput<<endl;
								}
								if(userInput[0]=='y'||userInput[0]=='Y')
								{
								listBuffStruct lbtemp;
								lbtemp.logtype = 1;
								memset(lbtemp.listBuff, '\0', 8192);
								char obj[256];
								strcpy(obj, "DELT");						
								msg_header deleteReq;
								createMsgHdrStr(&deleteReq,0xBC,initMap["TTL"].asDouble,obj,node_instance_id,95+strlen(storeTemp.fileName));
								fillMsgHdrBuffer(deleteReq, lbtemp.listBuff);
								char password[200];
								memset(password,'\0',200);
								char tc[20];
								memset(tc,'\0',20);
								struct timeval tvw;
								gettimeofday(&tvw,NULL);
								sprintf(tc,"%10ld.%03d",tvw.tv_sec,(int)tvw.tv_usec);
								SHA1((const unsigned char*)tc, strlen(tc),(unsigned char*)password);
								memcpy(&(deleteMessage[75+strlen(storeTemp.fileName)]),password,20);
								memcpy(&(lbtemp.listBuff[27]), deleteMessage,95+strlen(storeTemp.fileName));
								lbtemp.datalength = 27 + 95 + strlen(storeTemp.fileName);
								pthread_mutex_lock(&writeMapMutex);
								for(it=writeMap.begin(); it!=writeMap.end(); it++)
								{
									lbtemp.portNumber = (*it).first;
									writeListData listDataStr = writeMap[(*it).first];
									listDataStr.response.push_back(lbtemp);
									writeMap[(*it).first] = listDataStr;
								}
								pthread_mutex_unlock(&writeMapMutex);
								}
								else
								{
								
								}
							}
							else
							{
								char password[200];
								memset(password,'\0',200);
								fread(password, 1, 20, pFile);
								fclose(pFile);
								char noncebuf[SHA_DIGEST_LENGTH];
								SHA1((const unsigned char*)password, strlen(password),(unsigned char*)noncebuf);
								char nonce20b[20];
								convert40Bto20B(nonce20b,nonce);
								if(printFlag == 1)
								{
									for(int ii=0;ii<20;ii++)
										printf("%02x->%02x\n",(uint8_t)nonce20b[ii],(uint8_t)noncebuf[ii]);
								}
								if(memcmp(nonce20b,noncebuf,20)==0)
								{
									if(printFlag == 1)
									{
										cout<<"Match Found Deleting File"<<endl;
									}
									memcpy(&(deleteMessage[75+strlen(storeTemp.fileName)]),password,20);
									strcpy(storefilename,initMap["HomeDir"].asStr);
									strcat(storefilename,"/");
									strcat(storefilename,"files");
									strcat(storefilename,"/");
									strcat(storefilename,fc);
									char deletefilename[8192];
									memset(deletefilename,'\0',8192);
									strcpy(deletefilename,storefilename);
									strcat(deletefilename,".data");
									if( remove(deletefilename) != 0 )
									{
										perror( "Error deleting file" );
									}
									else
									{
										cout<<"File Has Been Deleted"<<endl;
										if(printFlag == 1)
										{
											printf("%s.data File successfully deleted\n",fc );
										}
									}
									memset(deletefilename,'\0',8192);
									strcpy(deletefilename,storefilename);
									strcat(deletefilename,".meta");
									if( remove(deletefilename) != 0 )
									{
										perror( "Error deleting file" );
									}
									else
									{
										if(printFlag == 1)
										{
											printf("%s.meta File successfully deleted\n",fc );
										}
									}
									memset(deletefilename,'\0',8192);
									strcpy(deletefilename,storefilename);
									strcat(deletefilename,".pass");
									if( remove(deletefilename) != 0 )
									{
										perror( "Error deleting file" );
									}
									else
									{
										if(printFlag == 1)
										{
											printf("%s.pass File successfully deleted\n",fc );
										}
									}
									if(printFlag == 1)
									{
										cout<<myStoreList.size()<<endl;
									}
									itF = myStoreList.erase(itF);
									pthread_mutex_lock(&searchFileIdsLock);
									list<search_fileId_results>::iterator itSeFileId;
									for(itSeFileId=searchFileIdsList.begin(); itSeFileId!=searchFileIdsList.end(); itSeFileId++)
									{
										search_fileId_results temp = *itSeFileId;
										if(temp.fileIndex == storeTemp.fileIndex)
										{
											searchFileIdsList.erase(itSeFileId);
											break;
										}
									}
									pthread_mutex_unlock(&searchFileIdsLock);
									if(printFlag == 1)
									{
										cout<<myStoreList.size()<<endl;
									}
								}
								listBuffStruct lbtemp;
								lbtemp.logtype = 1;
								memset(lbtemp.listBuff, '\0', 8192);
								char obj[256];
								strcpy(obj, "DELT");						
								msg_header deleteReq;
								createMsgHdrStr(&deleteReq,0xBC,initMap["TTL"].asDouble,obj,node_instance_id,95+strlen(storeTemp.fileName));
								fillMsgHdrBuffer(deleteReq, lbtemp.listBuff);
								memcpy(&(lbtemp.listBuff[27]), deleteMessage,95+strlen(storeTemp.fileName));
								lbtemp.datalength = 27 + 95 + strlen(storeTemp.fileName);
								pthread_mutex_lock(&writeMapMutex);
								for(it=writeMap.begin(); it!=writeMap.end(); it++)
								{
									lbtemp.portNumber = (*it).first;
									writeListData listDataStr = writeMap[(*it).first];
									listDataStr.response.push_back(lbtemp);
									writeMap[(*it).first] = listDataStr;
								}
								pthread_mutex_unlock(&writeMapMutex);
							}
						}
					}
				}
				strcpy(storefilename,initMap["HomeDir"].asStr);
				strcat(storefilename,"/");
				strcpy(filename,storefilename);
				strcat(filename,"kwrd_index");
				pFile=fopen(filename,"w");
				fclose(pFile);
				strcpy(filename,storefilename);
				strcat(filename,"sha1_index");
				pFile=fopen(filename,"w");
				fclose(pFile);
				strcpy(filename,storefilename);
				strcat(filename,"nonce_index");
				pFile=fopen(filename,"w");
				fclose(pFile);
				strcpy(filename,storefilename);
				strcat(filename,"name_index");
				pFile=fopen(filename,"w");
				fclose(pFile);
				if(printFlag == 1)
				{
					cout<<myStoreList.size()<<endl;
				}
				for(itF=myStoreList.begin(); itF!=myStoreList.end(); itF++)
				{
					if(printFlag == 1)
					{
						cout<<"enters"<<endl;
					}
					storeListStr storeData = *itF;
					strcpy(filename,initMap["HomeDir"].asStr);
					strcat(filename,"/");
					strcat(filename,"kwrd_index");
					pFile=fopen(filename,"a");
					fprintf(pFile,"%d=",storeData.fileIndex);
					int j =0;
					for(j=0;j<256;j++)
					{
						fprintf(pFile,"%c",storeData.fileBitVector[j]);
					}
					fprintf(pFile,"\n");
					fclose(pFile);

					//Create the name_index file
					strcpy(filename,initMap["HomeDir"].asStr);
					strcat(filename,"/");
					strcat(filename,"name_index");
					pFile=fopen(filename,"a");
					fprintf(pFile,"%d=",storeData.fileIndex);
					fprintf(pFile,"%s",storeData.fileName);
					fprintf(pFile,"\n");
					fclose(pFile);

					//Create the nonce_index file
					strcpy(filename,initMap["HomeDir"].asStr);
					strcat(filename,"/");
					strcat(filename,"nonce_index");
					pFile=fopen(filename,"a");
					fprintf(pFile,"%d=",storeData.fileIndex);
					for(j=0;j<20;j++)
					{
						fprintf(pFile,"%02x",(uint8_t)storeData.fileNonce[j]);
					}
					fprintf(pFile,"\n");
					fclose(pFile);

					//Create the sha1_index file
					strcpy(filename,initMap["HomeDir"].asStr);
					strcat(filename,"/");
					strcat(filename,"sha1_index");
					pFile=fopen(filename,"a");
					fprintf(pFile,"%d=",storeData.fileIndex);
					for(j=0;j<20;j++)
					{
						fprintf(pFile,"%02x",(uint8_t)storeData.fileSha1[j]);
					}
					fprintf(pFile,"\n");
					fclose(pFile);	
				}
				pthread_mutex_unlock(&storelock);
				cout<<"servant:"<<port_recieve<<"> ";
				fflush(stdout);
				gettimeofday(&time1,NULL);
				tv.tv_sec = initMap["AutoShutdown"].asDouble-(time1.tv_sec-starttime.tv_sec);
				tv.tv_usec = 0;
				retval = select(1, &rfds, NULL, NULL, &tv);
			}
			else if(strcmp(command, "get") == 0)
			{
				memset(getFile, '\0', 128);
				int getIndex = -1;
				while(str != NULL)
				{
					str = strtok(NULL, " ");
					if(str != NULL)
					{
						if(ind == 1)
						{
							getIndex = atoi(str);
						}
						if(ind == 2)
						{
							strcpy(getFile, str);
						}
						ind++;
					}
				}
				
				if(getIndex == -1)
				{
					cout<<"Arguments of get command are missing"<<endl;
					cout<<"servant:"<<port_recieve<<"> ";
					fflush(stdout);
					gettimeofday(&time1,NULL);
					tv.tv_sec = initMap["AutoShutdown"].asDouble-(time1.tv_sec-starttime.tv_sec);
					tv.tv_usec = 0;
					retval = select(1, &rfds, NULL, NULL, &tv);
				}
				else
				{
					get_request getReq;
					int dataLen = 0;
					bool foundGet = false;
					list<getSearchResults>::iterator itSearResList;
					for(itSearResList = searchResultList.begin(); itSearResList != searchResultList.end(); itSearResList++)
					{
						getSearchResults temp = *itSearResList;
						foundGet = false;
						if(getIndex == temp.getIndex)
						{
							foundGet = true;
							memset(getReq.fileId, '\0', 20);
							memset(getReq.fileSha1, '\0', 20);
							memcpy(&getReq.fileId, &(temp.fileId[0]), 20);
							memcpy(&getReq.fileSha1, &(temp.fileSha1[0]), 20);
							break;
						}
					}
					if(foundGet)
					{
						list<search_fileId_results>::iterator itSearFileIds;
						int n = -1;
						int fileIndex = -1;
						bool selfGet = false;
						//Get the fileIndex from the searchFileIdsList using the fileId sent in the request.
						for(itSearFileIds = searchFileIdsList.begin(); itSearFileIds != searchFileIdsList.end(); itSearFileIds++)
						{
							selfGet = false;
							n = memcmp(getReq.fileId, itSearFileIds->fileUOID, 20);
							if(n == 0)
							{
								fileIndex = itSearFileIds->fileIndex;
								selfGet = true;
								break;
							}
						}
						if(selfGet)
						{
							if(printFlag == 1)
							{
								cout<<"self get"<<endl;
							}
							struct stat st;
							int k = 0;		
							char dataFile[512];
							memset(dataFile, '\0', 512);
							strcpy(dataFile,initMap["HomeDir"].asStr);
							strcat(dataFile,"/");
							strcat(dataFile,"files");
							strcat(dataFile,"/");
							char indx[5];
							memset(indx, '\0', 5);
							sprintf(indx, "%d", fileIndex);
							strcat(dataFile,indx);
							strcat(dataFile,".data");
							k = stat(dataFile, &st);
							uint32_t dataSize = st.st_size;
							
							int forCounter = (dataSize)/(8192);
							int extraCounter = (dataSize)%(8192);
							
							FILE *fptr1, *fptr2;
							if(getFile[0]=='\0')
							{
								list<storeListStr>::iterator itMyStr;
								for(itMyStr = myStoreList.begin(); itMyStr != myStoreList.end(); itMyStr++)
								{
									storeListStr temp = *itMyStr;
									if(temp.fileIndex == fileIndex)
									{
										memcpy(getFile, temp.fileName, strlen(temp.fileName));
										break;
									}
								}
							}
							fptr2 = fopen(getFile, "r");
							bool fileReplace = true;
							if(fptr2 != NULL)
							{
								char userInput[4];
								cout<<"Do you want the file to be replaced [yes/no] - ";
								cin>>userInput;
								fflush(stdin);
								if(userInput[0]=='y'||userInput[0]=='Y')
								{
									
								}
								else
								{
									fileReplace = false;
								}
							}
							else
							{
								
							}
							fclose(fptr2);
							if(fileReplace)
							{
								fptr1 = fopen(dataFile, "r");
								fptr2 = fopen(getFile,"w");
								char chBuf[8192];
								if(forCounter == 0)
								{
									memset(chBuf, '\0', 8192);
									fread(chBuf, 1, extraCounter, fptr1);
									fwrite(chBuf, 1, extraCounter, fptr2);
								}
								else
								{
									for(int l=0; l<forCounter; l++)
									{
										memset(chBuf,'\0', 8192);
										fread(chBuf, 1, 8192, fptr1);
										fwrite(chBuf, 1, 8192, fptr2);
									}
									if(extraCounter != 0)
									{
										memset(chBuf, '\0', 8192);
										fread(chBuf, 1, extraCounter, fptr1);
										fwrite(chBuf, 1, extraCounter, fptr2);
									}
								}
								fclose(fptr1);
								fclose(fptr2);
								cout<<"File Has Been Created"<<endl;
							}
							cout<<"servant:"<<port_recieve<<"> ";
							fflush(stdout);
							gettimeofday(&time1,NULL);
							tv.tv_sec = initMap["AutoShutdown"].asDouble-(time1.tv_sec-starttime.tv_sec);
							tv.tv_usec = 0;
							retval = select(1, &rfds, NULL, NULL, &tv);
						}
						else
						{
							if(printFlag == 1)
							{
								cout<<"else get"<<endl;
							}
							dataLen = 20+20;
							char obj[256];
							strcpy(obj, "GTRQ");
							msg_header getRequest;
							createMsgHdrStr(&getRequest,0xDC,initMap["TTL"].asDouble,obj,node_instance_id, dataLen);
							
							//Push the requested uoid for matching during response requests
							getSTR getSTR;
							memset(getSTR.uoid, '\0', 20);
							memcpy(getSTR.uoid,getRequest.uoid,20);
							getResponseList.push_back(getSTR);
					
							listBuffStruct lbtemp;
							lbtemp.logtype = 1;
							memset(lbtemp.listBuff, '\0', 8192);
							fillMsgHdrBuffer(getRequest, lbtemp.listBuff);
							memcpy(&(lbtemp.listBuff[27]), &(getReq.fileId[0]), 20);
							memcpy(&(lbtemp.listBuff[47]), &(getReq.fileSha1[0]), 20);
							lbtemp.datalength = 27 + 20 + 20;
							pthread_mutex_lock(&writeMapMutex);
							for(it=writeMap.begin(); it!=writeMap.end(); it++)
							{
								lbtemp.portNumber = (*it).first;
								writeListData listDataStr = writeMap[(*it).first];
								listDataStr.response.push_back(lbtemp);
								writeMap[(*it).first] = listDataStr;
							}
							pthread_mutex_unlock(&writeMapMutex);
							
							cout<<"servant:"<<port_recieve<<"> ";
							fflush(stdout);
							gettimeofday(&time1,NULL);
							tv.tv_sec = initMap["AutoShutdown"].asDouble-(time1.tv_sec-starttime.tv_sec);
							tv.tv_usec = 0;
							retval = select(1, &rfds, NULL, NULL, &tv);
						}
					}
				}
			}
			else
			{
				cout<<"BAD COMMAND"<<endl;
				cout<<"servant:"<<port_recieve<<"> ";
				fflush(stdout);
				gettimeofday(&time1,NULL);
				tv.tv_sec = initMap["AutoShutdown"].asDouble-(time1.tv_sec-starttime.tv_sec);
				tv.tv_usec = 0;
				retval = select(1, &rfds, NULL, NULL, &tv);
			}
		}	
		usleep(1);
	}
	if(printFlag==1)
	{
		cout<<"tmc ends"<<endl;
	}
	fflush(stdout);
	pthread_exit(NULL);
}
